﻿using Dicom;
using Dicom.Imaging;
using DICOM_PROJECT.DAL;
using DICOM_PROJECT.DAL.Security;
using DICOM_PROJECT.Extension;
using DICOM_PROJECT.Models;
using EvilDicom.Image;
using EvilDICOM.Core;
using EvilDICOM.Core.Helpers;
using EvilDICOM.Core.Interfaces;
using EvilDICOM.Core.IO.Reading;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace DICOM_PROJECT.Controllers
{
    [CustomAuthorize(Roles = "Radiologist")]
    public class RadiologistController : BaseController
    {
        //static ImageMatrix dicom;
        //static DicomImage dicomImage;
        // GET: /Radiologist/
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public string GetPatientInfo(SearchModel search)
        {
            if(!ModelState.IsValid)
            {
                return "invalid_id";
            }
            var user = new UserProfile();
            if (search.type == 1)//search with patientID
            {
                user = db.UserProfiles.FirstOrDefault(m => m.UserProfileID == search.id);
            }
            else
            {
                user = db.UserProfiles.FirstOrDefault(m => m.SocialID == search.id.ToString() || m.SocialID == "0" + search.id.ToString());
            }
            if(user==null)
            {
                return "no_matched_data";
            }
            var userResult = new List<PatientModel>
            {
                new PatientModel { ID=user.UserProfileID, SocialID=user.SocialID, Name = user.Name, Birthday=user.Birthday, Male=user.Male, Address = user.Address, Phone = user.Phone }
            };

            PageModel indicationPage = new PageModel { RowsPerPage = 10, PageNumber = 1 };
            var indications = Pagination<Indication>.Page(user.Indications.OrderByDescending(i => i.IndicationID), indicationPage);
            var indicationResult = new List<IndicationModel>();
            indications.ForEach(i => indicationResult.Add(new IndicationModel { IndicationID = i.IndicationID, CreateDate = i.CreateDate, UpdateDate=i.UpdateDate, IndicationInformation = i.IndicationInformation }));

            var result = new ArrayList();
            result.Add(userResult);
            result.Add(indicationResult);
            result.Add(indicationPage);

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize(result);
        }

        [HttpPost]
        public string GetIndicationsPage(PageModel page)
        {
            var patient = new UserProfile();
            patient = db.UserProfiles.FirstOrDefault(m => m.UserProfileID == page.PatientID);
            PageModel indicationPage = new PageModel { RowsPerPage = page.RowsPerPage, PageNumber = page.PageNumber };
            var indications = Pagination<Indication>.Page(patient.Indications.OrderByDescending(v => v.IndicationID), indicationPage);
            var indicationResult = new List<IndicationModel>();
            indications.ForEach(i => indicationResult.Add(new IndicationModel { IndicationID = i.IndicationID, CreateDate = i.CreateDate, UpdateDate = i.UpdateDate, IndicationInformation = i.IndicationInformation }));
            var result = new ArrayList();
            result.Add(indicationResult);
            result.Add(indicationPage);

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize(result);
        }

        [HttpPost]
        public string GetIndication(string indicationID)
        {
            int id= Int32.Parse(indicationID);
            var indication = db.Indications.FirstOrDefault(i => i.IndicationID == id);
            var result = new ArrayList();
            if(indication!=null)
            {
                result.Add(new IndicationUpdateModel
                {
                    IndicationID = indication.IndicationID,
                    PatientID = indication.UserProfileID,
                    PatientName = indication.UserProfile.Name,
                    DoctorID = indication.DoctorID,
                    DoctorName = indication.Doctor.Name,
                    CreateDate = indication.CreateDate.ToString("HH:mm:ss dd/MM/yyyy"),
                    IndicationInformation = indication.IndicationInformation,
                    IndicationResult=indication.IndicationResult,
                    ImageVisitID = indication.ImageVisitID,
                    ImageID = indication.ImageID
                });
            }
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize(result);
        }

        //[HttpPost]
        //public string SaveIndication(List<IndicationUpdateModel> indications)
        //{
        //    try
        //    {
        //        //if (ModelState.IsValid)
        //        {
        //            //db.Entry(indications.First()).State = EntityState.Modified;
        //            //db.SaveChanges();
        //            var updateSQL = @"UPDATE Indication SET RadiologistID=@p0, UpdateDate=@p1, IndicationResult=@p2, ImageVisitID=@p3, ImageID=@p4 WHERE IndicationID=@p5";
        //            var rowCount = db.Database.ExecuteSqlCommand(updateSQL, User.UserID, DateTime.Now, indications[0].IndicationResult, indications[0].ImageVisitID, indications[0].ImageID, indications[0].IndicationID);
        //        }
        //        //else
        //        //{
        //        //    ModelState.AddModelError("", "Invalid data input!");
        //        //}
        //    }
        //    catch (DataException /* dex */)
        //    {
        //        //Log the error (uncomment dex variable name and add a line here to write a log.
        //        ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
        //    }

        //    var indication = db.Indications.Find(indications[0].IndicationID);
        //    var result = new ArrayList();
        //    result.Add(new IndicationModel { IndicationID = indication.IndicationID, CreateDate = indication.CreateDate, UpdateDate = indication.UpdateDate, IndicationInformation = indication.IndicationInformation });
        //    JavaScriptSerializer serializer = new JavaScriptSerializer();
        //    return serializer.Serialize(result);
        //}

        [HttpPost]
        public string SaveIndication(IndicationUpdateModel indication)
        {
            try
            {
                //if (ModelState.IsValid)
                {
                    //db.Entry(indications.First()).State = EntityState.Modified;
                    //db.SaveChanges();
                    var updateSQL = @"UPDATE Indication SET RadiologistID=@p0, UpdateDate=@p1, IndicationResult=@p2, ImageVisitID=@p3, ImageID=@p4 WHERE IndicationID=@p5";
                    var rowCount = db.Database.ExecuteSqlCommand(updateSQL, User.UserID, DateTime.Now, indication.IndicationResult, indication.ImageVisitID, indication.ImageID, indication.IndicationID);
                }
                //else
                //{
                //    ModelState.AddModelError("", "Invalid data input!");
                //}
            }
            catch (DataException /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
            }

            var indicationResult = db.Indications.Find(indication.IndicationID);
            var result = new ArrayList();
            result.Add(new IndicationModel { IndicationID = indicationResult.IndicationID, CreateDate = indicationResult.CreateDate, UpdateDate = indicationResult.UpdateDate, IndicationInformation = indicationResult.IndicationInformation });
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize(result);
        }

        private FileInfo[] FindPatientFolder(string patientID)
        {
            DirectoryInfo patientDir = new DirectoryInfo("C:\\Desktop\\" + patientID);
            if (!patientDir.Exists)
            {
                return null;
            }
            return patientDir.GetFiles();//!=null
        }

        private DicomImage FindPatientFile(string patientID, string studyUID)
        {
            FileInfo[] files = FindPatientFolder(patientID);
            if (files != null)//empty folder is not null
            {
                //DICOMObject dcm;
                //IDICOMElement studyID;
                //foreach (FileInfo file in files)
                //{
                //    dcm = DICOMFileReader.Read(file.FullName);
                //    studyID = dcm.FindFirst(TagHelper.STUDY_INSTANCE_UID);
                //    if (studyID != null && studyID.DData == studyUID)
                //    {
                //        //dicom = new ImageMatrix(file.FullName);
                //        dicomImage = new DicomImage(file.FullName);
                //        return dcm;
                //    }
                //}
                DicomFile dcm;
                string studyID;
                foreach (FileInfo file in files)
                {
                    dcm = DicomFile.Open(file.FullName);
                    studyID = dcm.Dataset.Get<string>(DicomTag.StudyInstanceUID);
                    if (studyID != null && studyID == studyUID)
                    {
                        HttpContext.Session["dicomImage"] = new DicomImage(file.FullName);
                        return new DicomImage(file.FullName);
                    }
                }
            }
            return null;//no file or match file found
        }

        private string FindPatientFilePath(string patientID, string studyUID)
        {
            FileInfo[] files = FindPatientFolder(patientID);
            if (files != null)//empty folder is not null
            {
                DICOMObject dcm;
                IDICOMElement studyID;
                foreach (FileInfo file in files)
                {
                    dcm = DICOMFileReader.Read(file.FullName);
                    studyID = dcm.FindFirst(TagHelper.STUDY_INSTANCE_UID);
                    if (studyID != null && studyID.DData == studyUID)
                    {
                        return file.FullName;
                    }
                }
            }
            return null;//no file or match file found
        }

        [HttpPost]
        public string ListOfImageVisit(PageModel page)
        {
            //DATABASE
            //int id = Int32.Parse(patientID);
            //var imageVisits = db.ImageVisits.Where(m => m.PatientID == id).ToList();
            //if (imageVisits.Count == 0)
            //{
            //    return "no_matched_data";
            //}
            //var imageVisitsResult = new ArrayList();
            //imageVisits.ForEach(i => imageVisitsResult.Add(new ImageVisitModel { ImageVisitID = i.ImageVisitID, CreateDate = i.CreateDate, Radiologist = i.Radiologist.Name, Description = i.Description }));
            //JavaScriptSerializer serializer = new JavaScriptSerializer();
            //return serializer.Serialize(imageVisitsResult);
            //return JsonConvert.SerializeObject(imageVisitsResult.ToList(), JsonRequestBehavior.AllowGet);

            //ALL FILES IN ONE FOLDER
            //DirectoryInfo dir = new DirectoryInfo("C:\\Desktop\\");
            //FileInfo[] files = dir.GetFiles();
            //DICOMObject dcm;
            //IDICOMElement dcmPatientID;
            //IDICOMElement studyID;
            //var imageVisitsResult = new ArrayList();
            //foreach (FileInfo file in files)
            //{
            //    //Console.WriteLine(file.FullName);

            //    dcm = DICOMFileReader.Read(file.FullName.ToString());
            //    dcmPatientID = dcm.FindFirst(TagHelper.PATIENT_ID);
            //    if (dcmPatientID != null && dcmPatientID.DData == patientID)
            //    {
            //        studyID = dcm.FindFirst(TagHelper.STUDY_INSTANCE_UID);
            //        imageVisitsResult.Add(new ImageVisitModel { ImageVisitID = studyID.DData});
            //        //Console.WriteLine(file.Name + " " + studyID.DData);
            //    }
            //}

            //ONE FOLDER PER PATIENT
            FileInfo[] files = FindPatientFolder(page.PatientID.ToString());
            if (files!=null)//empty folder is not null
            {
                var imageVisitsResult = new List<ImageVisitModel>();
                //DICOMObject dcm;
                //IDICOMElement studyID;
                //IDICOMElement studyDate;
                //IDICOMElement physicianName;
                //IDICOMElement studyDescription;
                DicomFile dcm;
                string studyID;
                string studyDate;
                string physicianName;
                string studyDescription;
                foreach (FileInfo file in files)
                {
                    //Console.WriteLine(file.FullName);
                    dcm = DicomFile.Open(file.FullName);//DICOMFileReader.Read(file.FullName.ToString());
                    studyID = dcm.Dataset.Get<string>(DicomTag.StudyInstanceUID);//dcm.FindFirst(TagHelper.STUDY_INSTANCE_UID);
                    studyDate = dcm.Dataset.Get<DateTime>(DicomTag.StudyTime).ToString("HH:mm:ss") + " " + dcm.Dataset.Get<DateTime>(DicomTag.StudyDate).ToString("dd/MM/yyyy");//dcm.FindFirst(TagHelper.STUDY_DATE);
                    physicianName = dcm.Dataset.Get<string>(DicomTag.ReferringPhysicianName);//dcm.FindFirst(TagHelper.REFERRING_PHYSICIAN_NAME);
                    studyDescription = dcm.Dataset.Get<string>(DicomTag.StudyDescription);//dcm.FindFirst(TagHelper.STUDY_DESCRIPTION);
                    imageVisitsResult.Add(new ImageVisitModel
                    {
                        ImageVisitID = studyID,// != null ? studyID.DData : null,
                        CreateDate = studyDate,// != null ? studyDate.DData : null,
                        Radiologist = physicianName,// != null ? physicianName.DData : null,
                        Description = studyDescription// != null ? studyDescription.DData : null
                    });
                }
                if(imageVisitsResult.Count>0)
                {
                    PageModel imageVisitPage = new PageModel { RowsPerPage = page.RowsPerPage, PageNumber = page.PageNumber };
                    imageVisitsResult.Sort();
                    imageVisitsResult = Pagination<ImageVisitModel>.Page(imageVisitsResult, imageVisitPage);
                    

                    var result = new ArrayList();
                    result.Add(imageVisitsResult);
                    result.Add(imageVisitPage);
                    JavaScriptSerializer serializer = new JavaScriptSerializer();
                    return serializer.Serialize(result);
                }
                else
                {
                    return "no_file_folder";
                }
            }
            else
            {
                return "no_patient_folder";
            }
        }

        [HttpPost]
        public string GetImageMeta(GetImageVisit dicomInfo)
        {
            //DEMO
            //string[] str = new string[1];
            //str[0] = "C:\\Desktop\\MR-MONO2-8-16x-heart.dcm";
            //var imgFile = new ImageMatrix(str[0]);
            //ViewBag.noOfFrame = imgFile.Properties.NumberOfFrames;
            //ViewBag.imgWidth = imgFile.Properties.Columns;
            //ViewBag.imgHeight = imgFile.Properties.Rows;
            //return View();

            DicomImage dcm = FindPatientFile(dicomInfo.PatientID, dicomInfo.ImageVisitID);
            if (dcm!=null)
            {
                //Console.WriteLine(patientDir.FullName + " is exist");
                var metaResult = new DicomMetaModel();
                //IDICOMElement NoOfFrame;
                //IDICOMElement ImageWidth;
                //IDICOMElement ImageHeight;
                //NoOfFrame = dcm.FindFirst(TagHelper.NUMBER_OF_FRAMES);
                //ImageWidth = dcm.FindFirst(TagHelper.COLUMNS);
                //ImageHeight = dcm.FindFirst(TagHelper.ROWS);
                int NoOfFrame;
                int ImageWidth;
                int ImageHeight;
                NoOfFrame = dcm.NumberOfFrames;
                ImageWidth = dcm.Width;
                ImageHeight = dcm.Height;
                metaResult.IDs = NoOfFrame;// != null ? NoOfFrame.DData : 0;
                metaResult.ImageWidth = ImageWidth;// != null ? ImageWidth.DData : 0;
                metaResult.ImageHeight = ImageHeight;// != null ? ImageHeight.DData : 0;
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                return serializer.Serialize(metaResult);
            }
            else
            {
                return "no_matched_file";
            }
        }

        [HttpGet]
        public FileContentResult GetImage(string patientID, string imageVisitID, int index)
        {
            //DEMO
            //string[] str = new string[1];
            //str[0] = "C:\\Desktop\\MR-MONO2-8-16x-heart.dcm";
            //var imgFile = new ImageMatrix(dicom);
            //Image image = imgFile.GetImage(index);
            //MemoryStream ms = new MemoryStream();
            //image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            //return new FileContentResult(ms.ToArray(), "image/*");

            //string filePath = FindPatientFilePath(patientID, imageVisitID);
            DicomImage dicom = ((DicomImage)HttpContext.Session["dicomImage"]);
            if (dicom!=null)//(filePath!=null)
            {
                //ImageMatrix im = new ImageMatrix(filePath);
                //DicomImage dicom = new DicomImage(filePath);
                //Image image = dicom.RenderImage(index);
                //Image image = RadiologistController.dicomImage.RenderImage(index);
                try//exception when change dicom file while request still processing
                {
                    Image image = dicom.RenderImage(index);
                    MemoryStream ms = new MemoryStream();
                    image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    return new FileContentResult(ms.ToArray(), "image/jpeg");
                }
                catch(Exception /*e*/)
                {
                    return null;
                }
            }
            return null;
        }

	}
}